package com.ziytek.web.citizen.caffeine;

import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.model.bean.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author fengh
 */

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CachePutOrGet {

    public void putCurrentCache(String key, LinkedList<DischargeData> value) {
        CaffeineUtil.set(CaffeineUtil.CURRENT_CACHE_PREFIX + key, value);
    }

    public void putFirstCurrentCache(String key, LinkedList<DischargeData> value) {
        CaffeineUtil.set(CaffeineUtil.FIRST_CURRENT_CACHE_PREFIX + key, value, 20);
    }

    public LinkedList<DischargeData> getFirstCurrentCache(String key) {
        return CaffeineUtil.get(CaffeineUtil.FIRST_CURRENT_CACHE_PREFIX + key);
    }


    public LinkedList<DischargeData> getCurrentCache(String key) {
        return CaffeineUtil.get(CaffeineUtil.CURRENT_CACHE_PREFIX + key);
    }


    public void deleteCurrentCacheStartWith(String key) {
        CaffeineUtil.deleteStartWith(CaffeineUtil.CURRENT_CACHE_PREFIX + key);
    }

    public void deleteCurrent(String key) {
        CaffeineUtil.delete(CaffeineUtil.CURRENT_CACHE_PREFIX + key);
    }

    public void putInterruptCapacityCache(String key, InterruptStatsCacheVo value) {
        //log.info("000000000中断容量缓存key:{}-{}", key, new Gson().toJson(value));
        CaffeineUtil.set(CaffeineUtil.INTERRUPT_CAPACITY_KEY + key, value, 10 * 60 * 60);
    }

    public InterruptStatsCacheVo getInterruptStatsCache(String key) {
        //log.info("容量获取缓存key:{}",key);
        return CaffeineUtil.get(CaffeineUtil.INTERRUPT_CAPACITY_KEY + key);
    }

    public void delInterruptStatsCache(String key) {
        //log.info("删除中断容量缓存key:{}", key);
        CaffeineUtil.delete(CaffeineUtil.INTERRUPT_CAPACITY_KEY + key);
    }

    public void putStatsCache(String key, CapStatsVo value) {
        // log.info("容量缓存key:{}",key);
        CaffeineUtil.set(CaffeineUtil.STATS_CACHE_PREFIX + key, value, 10 * 60 * 60);
    }

    public CapStatsVo getStatsCache(String key) {
        //log.info("容量获取缓存key:{}",key);
        return CaffeineUtil.get(CaffeineUtil.STATS_CACHE_PREFIX + key);
    }

    public void delStatsCache(String key) {
        CaffeineUtil.delete(CaffeineUtil.STATS_CACHE_PREFIX + key);
    }


    public List<CapStatsVo> getStatsCacheStartWith(String key) {
        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(CaffeineUtil.STATS_CACHE_PREFIX + key);

        if (CollectionUtils.isEmpty(map)) {
            return Collections.emptyList();
        }

        return map.values().stream()
                .filter(v -> v instanceof CaffeineUtil.CacheObject<?> cacheObject
                        && cacheObject.data instanceof CapStatsVo stats)
                .map(v -> (CapStatsVo) v.data)
                .toList();
    }

    public List<CommandIssuedSuccess> getCommandIssuedSuccessStartWith(String key) {
        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);

        if (CollectionUtils.isEmpty(map)) {
            return Collections.emptyList();
        }

        return map.values().stream()
                .filter(v -> v instanceof CaffeineUtil.CacheObject<?> cacheObject
                        && cacheObject.data instanceof CommandIssuedSuccess c)
                .map(v -> (CommandIssuedSuccess) v.data)
                .toList();
    }

    public void deleteStatsCache(String key) {
        CaffeineUtil.deleteStartWith(CaffeineUtil.STATS_CACHE_PREFIX + key);
    }

    public List<CommandConfirmation> getCommandConfirmationCacheStartWith(String cabinetNo) {

        var key = CaffeineUtil.COMMAND_CONFIRMATION + cabinetNo + CaffeineUtil.CACHE_KEY_CONNECTION_SYMBOL;
        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);

        if (CollectionUtils.isEmpty(map)) {
            return Collections.emptyList();
        }

        List<CommandConfirmation> result = map.values().stream()
                .filter(v -> v instanceof CaffeineUtil.CacheObject<?> cacheObject
                        && cacheObject.data instanceof CommandConfirmation cf && Boolean.TRUE.equals(cf.getSuccess()))
                .map(v -> (CommandConfirmation) v.data)
                .toList();

        if (CollectionUtils.isEmpty(result)) {
            return Collections.emptyList();
        }

        //log.info("getCommandConfirmationCacheStartWith key: {}. result getFirst: {}", key, result.getFirst());
        //return result.getFirst();
        return result;
    }

    public Map<String, String> getCommandIdsCacheStartWith(String idKey) {
        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(idKey);
        if (CollectionUtils.isEmpty(map)) {
            return Collections.emptyMap();
        }

        Map<String, String> result = new java.util.HashMap<>();
        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue() instanceof CaffeineUtil.CacheObject<?> cacheObject && cacheObject.data instanceof String v) {
                result.put(entry.getKey(), v);
            }
        }

        return result;
    }


    public Integer getOperateAllCache() {
        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(CaffeineUtil.CACHE_KEY_COMMAND_OPERATE_ALL);

        if (CollectionUtils.isEmpty(map)) {
            return NumConstant.INT_LT_ZERO;
        }

        var first = map.values().stream()
                .filter(v -> v instanceof CaffeineUtil.CacheObject<?> cacheObject
                        && cacheObject.data instanceof Integer ig)
                .findFirst();

        assert first.orElse(null) != null;
        return (Integer) first.orElse(null).data;
    }

}
